/**
* @author maze | guavestudios.com
* @license MIT License see LICENSE.TXT
* @version 0.1
*/
package com.guavestudios.fcon.core {
	import com.guavestudios.fcon.plugins.IConstantsProvider;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;

	/**
	* Class for parsing pathes in console
	* like: #name.@1.toString;
	* 
	* the #name stands for DisplayObject in navigateObject which has the name name
	* the @0 is the first element in a DisplayObjectContainer got by getChildAt()
	* the toString stands for an element property or function with no parameters
	*/
	public class PathParser implements IPathParser{
		
		//{ STATIC
	
		//}
		
		//{ MEMBERS
		private var navigateObject:Object;
		private var _constants:IConstantsProvider;
		//}
		
		//{ GETTER-SETTER
		/**
		* Get the relativ navigator object for the resolvement  
		*  
		*  @return DisplayObject
		*/
		public function getNavigateObject():Object {
			return this.navigateObject;
		}
		/**
		*  Set the relativ navigator object for the resolvement  
		*  @param pnavigateObject[DisplayObject]
		*  @return
		*/
		public function setNavigateObject(pnavigateObject:Object):void {
			this.navigateObject = pnavigateObject;
		}
		
		//}
		public function PathParser() {
			
			
			init();
		}
		private function init():void {
			
		}
		//{ PUBLIC FUNCTIONS
		/**
		* Parse the input an return an array with different objects depends on the object structur
		* prase the format test.test.@test
		* @param	path the path to parse
		* @return return an array of the current path elements
		*/
		public function parse(path:String):Array
		{
			var char:String;
			var isnumeric:Boolean=false;
			var issearch:Boolean = false;
			var isconstant:Boolean = false;
			var a:Array=[];
			var lastelement:PathElement;
			var lastfound:Object=navigateObject as Object;
			var cstring:String = "";
			
			
			
			for (var i:int=0,len:int=path.length; i<len; i++)
			{
				char = path.charAt(i);
				if (i==0 && navigateObject==null) {
					if (char != "$")
						return null;
				}
				if (char=="." || i==path.length-1) //last element or terminated by .
				{
					if (char!=".") 
					{
						cstring+=char;
					}
					if (isnumeric)
					{
						if (!lastfound) return null;
						isnumeric=false;
						var se:PathElement=new PathElement();
						se.setParent(lastelement);
						var parsei:int=parseInt(cstring);
						if (lastfound.numChildren<parsei) return null;
						se.setElement(lastfound.getChildAt(parsei));
						se.setElementId("@"+cstring);
						a.push(se);
						lastfound=se.getElement() as DisplayObjectContainer;
						lastelement=se;
					}
					else if (issearch)
					{
						if (!lastfound) return null;
						issearch=false;
						var se1:PathElement=new PathElement();
						se1.setParent(lastelement);
						var fdo:DisplayObject=lastfound.getChildByName(cstring);
						if (fdo==null) return null;
						se1.setElement(fdo);
						se1.setElementId("#"+cstring);
						a.push(se1);
						lastfound=se1.getElement() as DisplayObjectContainer;
						lastelement=se1;
					}
					else if (isconstant)
					{
						//if (!lastfound) return null;
						isconstant = false;
						if (_constants.hasConstant(cstring))
						{
							var selc:PathElement = new PathElement();
							selc.setElementId("$" + cstring);
							selc.setElement(_constants.getConstant(cstring));
							lastelement = selc;
							lastfound = selc.getElement();
							a.push(selc);
						}
						
						
					}
					else 
					{
						if (cstring.length>0)
						{
							
							var se2:PathElement=new PathElement();
							se2.setParent(lastelement);
							se2.setElementId(cstring);
							try {var fattr:*=lastfound[cstring]; }
							catch(e:Error) {return null; }
							if (fattr==null) return null;
							se2.setElement(fattr);
							lastelement = se2;
							lastfound = se2.getElement();
							a.push(se2);
						}
					}
					cstring="";
					
				}
				else if (char == " ") {
					if (a.length == 0) return null;
					return a;
				}
				else if (char=="@") //its numeric
				{
					isnumeric=true;
					continue;
				}
				else if (char=="#") //its identified by name
				{
					issearch=true;
					continue;
				}
				else if (char == "$")
				{
					isconstant = true;
					continue;
				}
				else //no special command
				{
					cstring+=char;
				}
			}
			return a;
		}
		
		public function get constants():IConstantsProvider { return _constants; }
		
		public function set constants(value:IConstantsProvider):void {
			_constants = value;
		}
		//}
		
		//{ OVERRIDEN METHODS
		
		//}
		
		//{ PRIVATE FUNCTIONS
		
		//}

	}
	
}
